package com.mystnihon.freeremote.manager;

import java.util.ArrayList;
import java.util.Observable;

import android.content.Context;
import android.net.Uri;
import android.util.Log;
import ca.benow.transmission.TransmissionClient;
import ca.benow.transmission.model.AddedTorrentInfo;
import ca.benow.transmission.model.TorrentStatus;

import com.mystnihon.freeremote.FreeRemoteApplication;
import com.mystnihon.freeremote.config.Config;
import com.mystnihon.freeremote.data.ListOfTorrentStatus;
import com.mystnihon.freeremote.data.MapOfSessionFieldAndObject;
import com.mystnihon.freeremote.db.table.SeedboxTable;
import com.mystnihon.freeremote.loader.torrent.AddTorrentRequest;
import com.mystnihon.freeremote.loader.torrent.GetSessionRequest;
import com.mystnihon.freeremote.loader.torrent.GetTorrentsLoader;
import com.mystnihon.freeremote.loader.torrent.GetTorrentsRequest;
import com.mystnihon.freeremote.loader.torrent.ReannounceTorrentRequest;
import com.mystnihon.freeremote.loader.torrent.RemoveTorrentRequest;
import com.mystnihon.freeremote.loader.torrent.StartStopTorrentRequest;
import com.mystnihon.freeremote.manager.TransmissionManager.TransmissionResult.ActionType;
import com.mystnihon.freeremote.manager.TransmissionManager.TransmissionResult.ResultType;
import com.mystnihon.loader.AbstractAsyncLoader.LoadingListener;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;

public class TransmissionManager extends Observable {

	private static final String TAG = TransmissionManager.class.getSimpleName();
	private final SpiceManager spiceManager = FreeRemoteApplication.spiceManager;
	private Context mContext;
	public TransmissionClient mTransmissionClient;
	private boolean mClientShouldBeInit = true;

	public TransmissionManager(Context context) {
		mContext = context;
	}

	public boolean hasInitClient() {
		if (Config.DEBUG_MODE_ENABLED)
			Log.d(TAG, "Ask if client init. Client init ?:" + (mTransmissionClient != null));
		return mTransmissionClient != null;
	}

	public boolean initTransmissionclient(SeedboxTable seedbox) {
		if (Config.DEBUG_MODE_ENABLED)
			Log.d(TAG, "initTransmission client");

		String host = seedbox.mHost;
		if (host != null) {
			int port = seedbox.seedboxPort;

			// FIXME Use this
			boolean identification = true;// prefs.getBoolean(mContext.getString(R.string.key_seedbox_use_identifiers),
											// false);
			String user = seedbox.seedboxLogin;
			String pass = seedbox.seedboxPassword;
			if (identification) {
				mTransmissionClient = new TransmissionClient(mContext, host, port, user, pass);
			} else {
				mTransmissionClient = new TransmissionClient(mContext, host, port);
			}
			mClientShouldBeInit = false;
			return true;
		}
		return false;
	}

	public boolean IsClientShouldBeInit() {
		return mClientShouldBeInit;
	}

	public void setClientShouldBeInit(boolean shouldReInit) {
		mClientShouldBeInit = shouldReInit; // I set than i should reinit the
											// client.
	}

	public void getTorrentList() {
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d(TAG, "get torrent list");
		}

		GetTorrentsRequest loader = new GetTorrentsRequest(mTransmissionClient);
		spiceManager.execute(loader, new RequestListener<ListOfTorrentStatus>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.GetTorrent, null));

			}

			@Override
			public void onRequestSuccess(ListOfTorrentStatus result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.GetTorrent, result));

			}
		});
	}

	public void startTorrent(int torrentId) {
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d(TAG, "get torrent list");
		}
		startStop(true, torrentId);
	}

	public void stopTorrent(int torrentId) {
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d(TAG, "get torrent list");
		}
		startStop(false, torrentId);
	}

	public void startTorrentAll() {
		startStop(true);
	}

	public void stopTorrentAll() {
		startStop(false);
	}

	private void startStop(boolean start, Object... torrentId) {
		final ActionType action = start ? ActionType.StartTorrent : ActionType.StopTorrent;
		StartStopTorrentRequest loader = new StartStopTorrentRequest(mTransmissionClient, start, torrentId);
		spiceManager.execute(loader, new RequestListener<Void>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, action, null));

			}

			@Override
			public void onRequestSuccess(Void result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, action, result));

			}
		});
	}

	public void removeTorrent(int torrentId, boolean removelocalfile) {
		RemoveTorrentRequest loader = new RemoveTorrentRequest(mTransmissionClient, removelocalfile, torrentId);
		spiceManager.execute(loader, new RequestListener<Void>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.RemoveTorrent, null));

			}

			@Override
			public void onRequestSuccess(Void result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.RemoveTorrent, result));

			}
		});
	}

	public void addTorrent(Uri torrent) {
		if (Config.DEBUG_MODE_ENABLED) {
			Log.d(TAG, "Add torrent :" + torrent);
		}
		AddTorrentRequest loader = new AddTorrentRequest(mContext, mTransmissionClient, torrent);
		spiceManager.execute(loader, new RequestListener<AddedTorrentInfo>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.AddTorrent, null));

			}

			@Override
			public void onRequestSuccess(AddedTorrentInfo result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.AddTorrent, result));

			}

		});
	}

	public void getSession() {
		GetSessionRequest loader = new GetSessionRequest(mTransmissionClient);
		spiceManager.execute(loader, new RequestListener<MapOfSessionFieldAndObject>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.GetSession, null));

			}

			@Override
			public void onRequestSuccess(MapOfSessionFieldAndObject result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.GetSession, result));

			}
		});
	}

	public void getTorrentDetails(TorrentStatus.TorrentField[] fields, int id) {
		GetTorrentsRequest loader = new GetTorrentsRequest(mTransmissionClient, fields, id);
		spiceManager.execute(loader, new RequestListener<ListOfTorrentStatus>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.GetTorrentDetails, null));

			}

			@Override
			public void onRequestSuccess(ListOfTorrentStatus result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.GetTorrentDetails, result));

			}
		});
	}

	public void reannounce(Object... ids) {
		ReannounceTorrentRequest request = new ReannounceTorrentRequest(mTransmissionClient, ids);
		spiceManager.execute(request, new RequestListener<Void>() {

			@Override
			public void onRequestFailure(SpiceException spiceException) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.ERROR, ActionType.Reannounce, null));

			}

			@Override
			public void onRequestSuccess(Void result) {
				setChanged();
				notifyObservers(new TransmissionResult(ResultType.SUCCESS, ActionType.Reannounce, result));

			}
		});

	}

	public static class TransmissionResult {
		public enum ResultType {
			SUCCESS, ERROR

		}

		public enum ActionType {
			GetTorrent, StartTorrent, StopTorrent, AddTorrent, RemoveTorrent, GetSession, GetTorrentDetails, Reannounce
		}

		public ResultType mSuccess;
		public Object mData;
		public ActionType mAction;

		public TransmissionResult(ResultType success, ActionType action, Object data) {
			mSuccess = success;
			mAction = action;
			mData = data;
		}
	}

	public void stopNetworkOperation() {
		spiceManager.cancelAllRequests();

	}
}
